#!/bin/bash
###############################################################################
#       脚本名称: json.sh
#       功能描述: JSON配置文件适配层，提供配置管理专用功能。
#       作者: 林再来
#       日期: 2025-10-15
#       版本: 1.0
#       功能:
#           1、json配置文件专用业务逻辑封装
#           2、多环境配置管理(base/dev/prod)
#           3、配置变更检测和监控
#           4、配置快照、备份和回滚
#           5、配置热重载支持
#           6、配置导入导出
#       依赖(插件/命令):
#           1、utils/utils_jq.sh - JSON数据处理工具
#           2、md5sum或cksum - 哈希计算
###############################################################################

# 防止重复加载
if [[ -n "${json_sh_loaded:-}" ]]; then
    return 0
fi
readonly json_sh_loaded=1

# 注意：不使用严格模式，避免影响交互式 shell

# 获取脚本目录和项目根目录（如果尚未定义）
if [[ -z "${script_dir:-}" ]]; then
    script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    readonly script_dir
fi

if [[ -z "${project_root:-}" ]]; then
    project_root="$(cd "${script_dir}/../.." && pwd)"
    readonly project_root
fi

# 加载依赖的工具层
if [[ -f "${project_root}/scripts/utils/utils_jq.sh" ]]; then
    source "${project_root}/scripts/utils/utils_jq.sh"
else
    echo "[ERROR] 无法加载依赖模块: utils_jq.sh" >&2
    return 1
fi

###############################################################################
# 全局常量
###############################################################################

readonly JSON_SNAPSHOT_DIR_SUFFIX=".snapshots"
readonly JSON_HASH_FILE_SUFFIX=".hash"

###############################################################################
# 全局变量
###############################################################################

declare -A JSON_WATCH_PIDS    # 配置文件监控进程PID映射

###############################################################################
# 基础配置操作（代理到工具层）
###############################################################################

# 函数: 读取配置值
function json_read() {
    local json_file="$1"
    local key="$2"
    
    utils_jq_read "$json_file" "$key"
}

# 函数: 写入配置值
function json_write() {
    local json_file="$1"
    local key="$2"
    local value="$3"
    local value_type="${4:-string}"
    
    utils_jq_write "$json_file" "$key" "$value" "$value_type"
}

# 函数: 删除配置键
function json_delete() {
    local json_file="$1"
    local key="$2"
    
    utils_jq_delete "$json_file" "$key"
}

###############################################################################
# 多环境配置管理
###############################################################################

# 函数: 合并多环境配置
function json_merge_env() {
    local base_file="$1"
    local env_file="$2"
    local output_file="$3"
    
    if [[ -z "$base_file" ]] || [[ -z "$env_file" ]] || [[ -z "$output_file" ]]; then
        log_error "json" "错误: 缺少参数: 基础配置文件、环境配置文件和输出文件路径"
        return 1
    fi
    
    if [[ ! -f "$base_file" ]]; then
        log_error "json" "错误: 基础配置文件不存在: $base_file"
        return 1
    fi
    
    if [[ ! -f "$env_file" ]]; then
        log_error "json" "错误: 环境配置文件不存在: $env_file"
        return 1
    fi
    
    log_info "json" "合并环境配置: $base_file + $env_file -> $output_file"
    
    # 先复制基础配置到输出文件
    cp "$base_file" "$output_file" || {
        log_error "json" "错误: 无法创建输出文件: $output_file"
        return 1
    }
    
    # 使用merge模式合并环境配置
    if utils_jq_merge "$output_file" "$env_file" "merge"; then
        log_info "json" "环境配置合并成功"
        return 0
    else
        log_error "json" "错误: 环境配置合并失败"
        return 1
    fi
}

###############################################################################
# 配置变更检测
###############################################################################

# 函数: 计算配置文件哈希值
function json_get_hash() {
    local json_file="$1"
    shift
    local keys=("$@")
    
    if [[ -z "$json_file" ]]; then
        log_error "json_config" "错误: 缺少参数: JSON配置文件路径"
        return 1
    fi
    
    if [[ ! -f "$json_file" ]]; then
        log_error "json_config" "错误: JSON配置文件不存在: $json_file"
        return 1
    fi
    
    log_debug "json_config" "计算配置文件哈希值: $json_file"
    
    local content=""
    
    if [[ ${#keys[@]} -eq 0 ]]; then
        # 计算整个文件的内容哈希
        content=$(utils_jq_query "$json_file" '.' 2>/dev/null | sort)
    else
        # 计算指定键的值的哈希
        for key in "${keys[@]}"; do
            local value
            value=$(json_read "$json_file" "$key")
            content="${content}${key}=${value}"
        done
    fi
    
    # 计算哈希值
    if command -v md5sum >/dev/null 2>&1; then
        echo -n "$content" | md5sum | cut -d' ' -f1
    elif command -v cksum >/dev/null 2>&1; then
        echo -n "$content" | cksum | cut -d' ' -f1
    else
        echo -n "${#content}-$(echo -n "$content" | head -c1)-$(echo -n "$content" | tail -c1)"
    fi
}

# 函数: 保存配置文件哈希值
function json_save_hash() {
    local json_file="$1"
    local hash_file="${2:-}"
    shift 2 2>/dev/null || shift 1
    local keys=("$@")
    
    if [[ -z "$json_file" ]]; then
        log_error "json_config" "错误: 缺少参数: JSON配置文件路径"
        return 1
    fi
    
    if [[ -z "$hash_file" ]]; then
        hash_file="${json_file}${JSON_HASH_FILE_SUFFIX}"
    fi
    
    log_debug "json_config" "保存配置哈希值: $json_file -> $hash_file"
    
    local hash_value
    if [[ ${#keys[@]} -eq 0 ]]; then
        hash_value=$(json_get_hash "$json_file")
    else
        hash_value=$(json_get_hash "$json_file" "${keys[@]}")
    fi
    
    if [[ $? -ne 0 ]] || [[ -z "$hash_value" ]]; then
        log_error "json_config" "错误: 计算哈希值失败"
        return 1
    fi
    
    if echo "$hash_value" > "$hash_file"; then
        log_debug "json_config" "哈希值已保存: $hash_value"
        return 0
    else
        log_error "json_config" "错误: 保存哈希值失败: $hash_file"
        return 1
    fi
}

# 函数: 检查配置文件是否发生变更
function json_check_changed() {
    local json_file="$1"
    local hash_file="${2:-}"
    shift 2 2>/dev/null || shift 1
    local keys=("$@")
    
    if [[ -z "$json_file" ]]; then
        log_error "json_config" "错误: 缺少参数: JSON配置文件路径"
        return 1
    fi
    
    if [[ ! -f "$json_file" ]]; then
        log_error "json_config" "错误: JSON配置文件不存在: $json_file"
        return 1
    fi
    
    if [[ -z "$hash_file" ]]; then
        hash_file="${json_file}${JSON_HASH_FILE_SUFFIX}"
    fi
    
    log_debug "json_config" "检查配置文件变更: $json_file"
    
    if [[ ! -f "$hash_file" ]]; then
        log_debug "json_config" "哈希文件不存在，视为已变更: $hash_file"
        return 0
    fi
    
    local saved_hash
    saved_hash=$(cat "$hash_file" 2>/dev/null | head -1)
    if [[ -z "$saved_hash" ]]; then
        log_debug "json_config" "无法读取保存的哈希值，视为已变更"
        return 0
    fi
    
    local current_hash
    if [[ ${#keys[@]} -eq 0 ]]; then
        current_hash=$(json_get_hash "$json_file")
    else
        current_hash=$(json_get_hash "$json_file" "${keys[@]}")
    fi
    
    if [[ $? -ne 0 ]] || [[ -z "$current_hash" ]]; then
        log_error "json_config" "错误: 计算当前哈希值失败"
        return 1
    fi
    
    if [[ "$current_hash" != "$saved_hash" ]]; then
        log_debug "json_config" "检测到配置变更 (当前: $current_hash, 保存: $saved_hash)"
        return 0
    else
        log_debug "json_config" "配置未发生变更"
        return 1
    fi
}

###############################################################################
# 配置快照和回滚
###############################################################################

# 函数: 创建配置快照
function json_create_snapshot() {
    local json_file="$1"
    local snapshot_dir="${2:-}"
    local comment="${3:-}"
    
    if [[ -z "$json_file" ]]; then
        log_error "json_config" "错误: 缺少参数: JSON配置文件路径"
        return 1
    fi
    
    if [[ ! -f "$json_file" ]]; then
        log_error "json_config" "错误: JSON配置文件不存在: $json_file"
        return 1
    fi
    
    if [[ -z "$snapshot_dir" ]]; then
        snapshot_dir="${json_file}${JSON_SNAPSHOT_DIR_SUFFIX}"
    fi
    
    mkdir -p "$snapshot_dir" || {
        log_error "json_config" "错误: 无法创建快照目录: $snapshot_dir"
        return 1
    }
    
    local timestamp=$(date +%Y%m%d_%H%M%S)
    local snapshot_file="$snapshot_dir/snapshot_$timestamp.json"
    local meta_file="$snapshot_dir/snapshot_$timestamp.meta"
    
    log_debug "json_config" "创建配置快照: $json_file -> $snapshot_file"
    
    if cp "$json_file" "$snapshot_file"; then
        cat > "$meta_file" << EOF
# JSON配置快照元数据
original_file: $json_file
snapshot_time: $(date '+%Y-%m-%d %H:%M:%S')
snapshot_timestamp: $timestamp
comment: ${comment:-无注释}
file_size: $(wc -c < "$json_file" 2>/dev/null || echo "unknown")
file_hash: $(json_get_hash "$json_file")
EOF
        
        log_info "json_config" "配置快照创建成功: $snapshot_file"
        echo "$snapshot_file"
        return 0
    else
        log_error "json_config" "错误: 配置快照创建失败"
        return 1
    fi
}

# 函数: 回滚到指定快照
function json_rollback() {
    local json_file="$1"
    local snapshot_file="$2"
    
    if [[ -z "$json_file" ]] || [[ -z "$snapshot_file" ]]; then
        log_error "json_config" "错误: 缺少参数: JSON配置文件路径和快照文件路径"
        return 1
    fi
    
    if [[ ! -f "$snapshot_file" ]]; then
        log_error "json_config" "错误: 快照文件不存在: $snapshot_file"
        return 1
    fi
    
    log_info "json_config" "回滚配置: $json_file <- $snapshot_file"
    
    # 在回滚前创建当前配置的快照
    json_create_snapshot "$json_file" "" "回滚前自动快照" >/dev/null
    
    if cp "$snapshot_file" "$json_file"; then
        log_info "json_config" "配置回滚成功"
        return 0
    else
        log_error "json_config" "错误: 配置回滚失败"
        return 1
    fi
}

###############################################################################
# 配置导入导出
###############################################################################

# 函数: 导出配置到指定目录
function json_export() {
    local json_file="$1"
    local export_dir="$2"
    
    if [[ -z "$json_file" ]] || [[ -z "$export_dir" ]]; then
        log_error "json_config" "错误: 缺少参数: JSON配置文件路径和导出目录"
        return 1
    fi
    
    if [[ ! -f "$json_file" ]]; then
        log_error "json_config" "错误: JSON配置文件不存在: $json_file"
        return 1
    fi
    
    mkdir -p "$export_dir" || {
        log_error "json_config" "错误: 无法创建导出目录: $export_dir"
        return 1
    }
    
    local timestamp=$(date +%Y%m%d_%H%M%S)
    local export_file="$export_dir/$(basename "$json_file" .json)_$timestamp.json"
    
    log_info "json_config" "导出配置: $json_file -> $export_file"
    
    if cp "$json_file" "$export_file"; then
        log_info "json_config" "配置导出成功: $export_file"
        echo "$export_file"
        return 0
    else
        log_error "json_config" "错误: 配置导出失败"
        return 1
    fi
}

# 函数: 从文件导入配置
function json_import() {
    local source_file="$1"
    local target_file="$2"
    
    if [[ -z "$source_file" ]] || [[ -z "$target_file" ]]; then
        log_error "json_config" "错误: 缺少参数: 源文件路径和目标配置文件路径"
        return 1
    fi
    
    if [[ ! -f "$source_file" ]]; then
        log_error "json_config" "错误: 源文件不存在: $source_file"
        return 1
    fi
    
    # 验证源文件格式
    if ! utils_jq_validate "$source_file"; then
        log_error "json_config" "错误: 源文件格式无效"
        return 1
    fi
    
    log_info "json_config" "导入配置: $source_file -> $target_file"
    
    # 如果目标文件存在，先创建快照
    if [[ -f "$target_file" ]]; then
        json_create_snapshot "$target_file" "" "导入前自动快照" >/dev/null
    fi
    
    if cp "$source_file" "$target_file"; then
        log_info "json_config" "配置导入成功"
        return 0
    else
        log_error "json_config" "错误: 配置导入失败"
        return 1
    fi
}

###############################################################################
# 帮助函数
###############################################################################

# 函数: 显示帮助信息
function json_help() {
    cat << 'EOF'
JSON配置管理适配层 (json.sh) - 使用说明

基础操作：
  json_read <file> <key>              - 读取配置值
  json_write <file> <key> <value> [type] - 写入配置值
  json_delete <file> <key>            - 删除配置键

多环境管理：
  json_merge_env <base> <env> <output>  - 合并环境配置

变更检测：
  json_get_hash <file> [keys...]          - 计算配置哈希
  json_save_hash <file> [hash_file] [keys...] - 保存哈希值
  json_check_changed <file> [hash_file] [keys...] - 检查变更

快照和回滚：
  json_create_snapshot <file> [dir] [comment] - 创建快照
  json_rollback <file> <snapshot>           - 回滚到快照

导入导出：
  json_export <file> <dir>          - 导出配置
  json_import <source> <target>     - 导入配置

注意事项：
  1. 本模块专注于配置管理业务逻辑
  2. 底层数据操作依赖 utils/utils_jq.sh

EOF
}

###############################################################################
# 简单日志函数（如果外部日志模块不可用）
###############################################################################

if ! command -v log_debug >/dev/null 2>&1; then
    function log_debug() { 
        local module="${1:-}"
        shift
        echo "[DEBUG] [$module] $*" >&2
    }
fi

if ! command -v log_info >/dev/null 2>&1; then
    function log_info() {
        local module="${1:-}"
        shift
        echo "[INFO]  [$module] $*" >&2
    }
fi

if ! command -v log_warn >/dev/null 2>&1; then
    function log_warn() {
        local module="${1:-}"
        shift
        echo "[WARN]  [$module] $*" >&2
    }
fi

if ! command -v log_error >/dev/null 2>&1; then
    function log_error() {
        local module="${1:-}"
        shift
        echo "[ERROR] [$module] $*" >&2
    }
fi

